#ifndef TB_REFLECTION_ALLOCATOR_TRAITS_H__
#define TB_REFLECTION_ALLOCATOR_TRAITS_H__

#include "tbcore/predefined.hpp"

#include "type_traits.hpp"

TB_NAMESPACE_BEGIN

namespace reflection {

template <class T, typename Enabled = void>
struct DefaultAllocatorTrait {
	static void* Malloc(const void* copy = 0) {
		if (copy) {
      LKERNEL() << _T("type is not copy constructible");
		} 
		return ::new T();
	};

	static void Free(void* p) {
		::delete reinterpret_cast<T*>(p);
	};
};

template <class T> struct
DefaultAllocatorTrait<T, typename enable_if<is_copy_constructible<T>::value >::type > {
  static void* Malloc(const void* copy = 0) {
    if (copy) {
      return ::new T(*static_cast<const T*>(copy));
    }
    return ::new T();
  };

  static void Free(void* p) {
    ::delete reinterpret_cast<T*>(p);
  };
};

template <class T> struct 
DefaultAllocatorTrait<T, typename enable_if<is_abstract<T>::value >::type > {
	static void* Malloc(const void* copy = 0) {
		(void)copy;
		LKERNEL() << _T("cannot instantiate abstract class");
		return nullptr;
	};

	static void Free(void* p) {
		(void)p;
	};
};

} //namespace reflection

TB_NAMESPACE_END

#endif // TB_REFLECTION_ALLOCATOR_TRAITS_H__
